/**
 * This software implements a CAT-1 LTE baseband.
 *
 * dl_const.h --
 *
 * Copyright (C) 2015  Optimum Semiconductor Technologies, Inc. info@optimumsemi.com

 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.

 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

//#ifndef DL_CONST_H_
//#define DL_CONST_H_
#include <stdarg.h>

#include <stdio.h>                           /* before printf gets redef.   */

#ifdef __SANDBLASTER__
// header file for SandBlaster intrinsics
#  include <intrinsics.h>
#  include <os/overlay.h>
#else
// allows GCC to run SandBlaster code
//#  include "sbintrinsics.h"
#endif

#ifndef UE_CATEGORY
#define UE_CATEGORY				1
#endif

#ifndef TEST_UPLINK
#define TEST_UPLINK				0
#endif

#if (DEMO_GUI == 0)

#define DEMO_PRINT_AGC(x)	

#define DEMO_PRINT(x)
//#define PRINT_FUNC(...) 		PRINT_FUNC_TYPE(__VA_ARGS__)
//#define PRINT_FUNC_DETAIL(...)
//#define PRINT_OVERLAYS(...) 	printf(__VA_ARGS__)

#else

#ifdef DISPLAY_AGC
#define DEMO_PRINT_AGC(x)		(x)
#else
#define DEMO_PRINT_AGC(x)	
#endif

#define DEMO_PRINT(x)			{(x); SPIN(4);}
#define PRINT_FUNC(...)
#define PRINT_FUNC_DETAIL(...)
#define PRINT_OVERLAYS(...)

#endif

#ifdef RUN_L1CTRL
#define ENABLE_L1CTRL(x)		(x)
#define DISABLE_L1CTRL(x)	
#else
#define ENABLE_L1CTRL(x)	
#define DISABLE_L1CTRL(x)		(x)
#endif

#ifdef POWER_SAVINGS
#   error "not this one"
#define DO_POWER_SAVINGS(x)		(x)
#else
#define DO_POWER_SAVINGS(x)
#endif

#define MEASURE_CTC_CYCS       	0

#if (MEASURE_CTC_CYCS == 1)
#define GET_CTC_CYCLES(x)		(x)
#else
#define GET_CTC_CYCLES(x)	
#endif

typedef enum {
	DL_SYSTEM_CLEAR=0,
	DL_SYSTEM_RESYNC
} lte_system_status;

#define RX_PSD_CORE_NUM			0
#define RX_PSD_CORE				(9+RX_PSD_CORE_NUM)

// this must be defined in the makefile, because both dl_cellsearch_tracking
// and dl_fe_be must use the same value
#ifndef LG2_INPUT_SYMBOL_SIZE
//#  error "LG2_INPUT_SYMBOL_SIZE must be defined in the Makefile - AJH"
#endif
#ifndef LTE_DL_TRACKING_FFT_SIZE
//#  error "LTE_DL_TRACKING_FFT_SIZE must be defined in the Makefile - AJH"
#endif

#if LTE_DL_TRACKING_FFT_SIZE == 1024
#  define FFT_OUT_OFFSET_BITS	5
#elif LTE_DL_TRACKING_FFT_SIZE == 2048
#  define FFT_OUT_OFFSET_BITS	6
#else
//#  error "LTE_DL_TRACKING_FFT_SIZE must be 1024 or 2048 - AJH"
#endif

#define MAX_DL_THREADS			12
#define MAX_NUM_SF_AVAIL		16
		
#define CELLSEARCH_TIMEOUT		100
#define PDCCH_TRY_NUM_RNTI		9

#define MAX_HARQ_PROCESSES		8
#define MIN_TBS_BLOCK_SIZE      40

#ifndef RUN_L1CTRL
#define MAX_TBS_BLOCK_SIZE      37000
#else
#define MAX_TBS_BLOCK_SIZE      10000
#endif

#define USE_PRECOMPUTED_DESCRAMBLER_TABALE	1
#define MAX_PDSCH_BLOCKS        8

#ifndef MAX_MU
#define MAX_MU					(25*2)
#endif

#define MAX_DCI_SIZE			47
#define MAX_DCI_BLOCK_SIZE 		96

#define CRC_BLOCK_SIZE			20000

#ifndef RUN_L1CTRL
#define FAILURE_RATE			50
#else
#define FAILURE_RATE			200
#endif

#define BE_TPUS					4
#define BE_IDLE_TPUS			0

#define RX_BE_CORE				1
#define FE_THREAD0				0
#define FE_THREAD1				1
#define FE_THREAD2				2
#define FE_THREAD3				3
#define BE_THREAD1				(4+1)
#define BE_THREAD2				(4+0)
#define BE_THREAD3				(4+2)
#define BE_THREAD4				(4+3)

#define MIN_CONTROL_SIZE		1
#define MAX_CONTROL_SIZE		4

#define MAX_N_RB_BMP_SIZE		(110)

typedef enum {
	LTE_DL_PERFORM_AGC=1,
	LTE_DL_PERFORM_MEASUREMENTS,
	LTE_DL_PERFORM_MEASUREMENTS_DONE,
	LTE_DL_PERFORM_SERVING_CELL_MEASUREMENTS,
	LTE_DL_PERFORM_NEIGHBOR_CELL_MEASUREMENTS
} lte_agc_measurements;

/* number of RBs for different bandwidths */
typedef enum {
	N_RB_1P4_MHZ = 6,
	N_RB_3_MHZ = 15,
	N_RB_5_MHZ = 25,
	N_RB_10_MHZ = 50,
	N_RB_15_MHZ = 75,
	N_RB_20_MHZ = 100
} lte_rb_bandwidths;

/* Bandwidth in KHz */
typedef enum {
	BW_1P4_MHZ = 1400,
	BW_3_MHZ = 3000,
	BW_5_MHZ = 5000,
	BW_10_MHZ = 10000,
	BW_15_MHZ = 15000,
	BW_20_MHZ = 20000
} lte_bandwidths;

typedef enum
{
    PHICH_Duration_normal,
    PHICH_Duration_extended
} lte_phich_durations;

typedef enum
{
    PHICH_Resource_oneSixth,
    PHICH_Resource_half,
    PHICH_Resource_one,
    PHICH_Resource_two
} lte_phich_resources;

typedef enum
{
    AntennaPortsCount_an1,
    AntennaPortsCount_an2,
    AntennaPortsCount_an4,
    AntennaPortsCount_spare1
} lte_antenna_ports_count;

typedef enum
{
	p_a_dB_6,
	p_a_dB_3,
	p_a_dB_2,
	p_a_dB_1,
	p_a_dB0,
	p_a_dB1,
	p_a_dB2,
	p_a_dB3
} lte_pdsch_config_p_a;

#define MIN(_x, _y) (_x) < (_y) ? (_x) : (_y);

#ifdef __SANDBLASTER__
/* For using SYNC register */
	#define SET_SYNC_BIT(bit)       (__sb_ctsr(1<<bit, MACH_SYNC1))
	#define UNSET_SYNC_BIT(bit)     (__sb_ctsr(1<<bit, MACH_SYNC0))
	#define SET_SYNC(value)         (__sb_ctsr(value, MACH_SYNC1))
	#define UNSET_SYNC(value)       (__sb_ctsr(value, MACH_SYNC0))

	#define GET_SYNCBIT(bit)        ((__sb_cfsr(MACH_SYNC0)>>bit) & 0x1)
	#define GET_SYNC()              (__sb_cfsr(MACH_SYNC0))
#else
	extern unsigned int sync_reg_gcc;

	#define SET_SYNC_BIT(bit)       (sync_reg_gcc |= (1<<bit))
	#define UNSET_SYNC_BIT(bit)     (sync_reg_gcc &= (~(1<<bit)))
	#define SET_SYNC(value)         (sync_reg_gcc |= value)
	#define UNSET_SYNC(value)       (sync_reg_gcc &= (~value))

	#define GET_SYNCBIT(bit)        ((sync_reg_gcc >> bit) & 0x1)
	#define GET_SYNC()              (sync_reg_gcc)
#endif

#define SYNCREG_FE_MASK			(0x30) //2 bits
#define LTE_DL_FE_TRK_FLAG_BIT	4
#define LTE_DL_TRK_FE_FLAG_BIT	5
#define LTE_DL_PDCCH_SLAVE_FLAG_BIT	7

#ifndef BCH_SOFTBUFSIZE
#define BCH_SOFTBUFSIZE				(1920+32)
#endif

#ifndef MAX_PDCCH_BUFSIZE
#define MAX_PDCCH_BUFSIZE			6264
#endif

#define DL_C_RNTI                   1
#define DL_SI_RNTI		  			0xFFFF
#define DL_RA_RNTI		  			0x80

#define WAIT_RADIO_FRAMES			4

#define MAX_CELL_ELEMENTS			32
#define MAX_PDSCH_BUFSIZE			5

#define ANT1_PDSCH_SCALE			(short)(0.7071*(1<<15))
#define ANT2_PDSCH_SCALE			(short)(0.5*(1<<15))

#define MAX_TXANTS					2

#if MULTI_TXANTS == 1
#define DL_ANTENNA_CONFIG			0
#elif MULTI_TXANTS == 2
#define DL_ANTENNA_CONFIG			1
#else
#define DL_ANTENNA_CONFIG			2
#endif


#define MAX_BCH_FAIL				2

#define MAX_CHAN_SYMS				7600 //for control size=1 and full allocation
#define MAX_HARQ_TRIALS				4

/* Antenna Configuration */
#ifdef ENABLE_MRC
#define MAX_RXANTS					2
#else
#define MAX_RXANTS					1
#endif

#define DSP_SPEED					(550) //(600)
#define CRYSTAL_SPEED				(30) /* sampling rate */
#define FE_REALTIME_CYCLES			((DSP_SPEED*(2048+144))/(4*CRYSTAL_SPEED)) /* per symbol */
#define BE_REALTIME_CYCLES			((DSP_SPEED*1000)/4) /* 1msec per sf */

#define MAX_CANDIDATES_PER_DCI			22
#define MAX_CANDIDATES_PER_DCI_COMMON	6
#define MAX_CANDIDATES_PER_DCI_UE		16

#define MAX_NUM_RNTIS					4

#define CODED_TAILBITS          		4
#define CODED_SLACKBUFFER       		(2048+1536)
#define MAX_INPUTS 						6400

#define MAX_DCI_PAYLOAD_NUMS			34
#define MIN_DCI_SIZE					13

//for now upto qam16 (only for buffer size)
#define MAX_SUPPORTED_MODULATION	6

#define BE_SOFTBITS_SIZE_PER_SF		(MAX_CHAN_SYMS*MAX_SUPPORTED_MODULATION+128)

#define PDCCH_FRAME_UNAVAILABLE		(-1)
#define PDCCH_FRAME_AVAILABLE		(1)

#define BCH_FRAME_AVAILABLE			(1)
#define BCH_FRAME_UNAVAILABLE		(-1)

#define PDSCH_FRAME_UNAVAILABLE		(-1)

#define MAX_SFN_COUNT				1024

#define SFN_SAT(x)	(((x-1) < 0) ? (MAX_SFN_COUNT-1): (x-1))

#define BCH_MODULATION		1
#define BCH_SFNUM			0

#define DEROTATION_WINDOW	128

#define ENABLE_DCI_PARSING	1

#define DL_PDSCH_RA                     0
#define DL_PDSCH_RB                     0

/* Bandwidth Specific Parameters */
#define DL_N_RB_FIXED		N_RB_10_MHZ
#define DL_BW_FIXED			BW_10_MHZ
#define MAX_DL_N_RB			50
#define MAX_DL_FFT_SIZE		2048
#define MAX_DL_CP1			((512*MAX_DL_FFT_SIZE)/2048)
#define MAX_DL_CP2			((512*MAX_DL_FFT_SIZE)/2048)

#define RB_LEN				12

#define TRK_MAX_PILOT_SIZE 	(2*MAX_DL_N_RB)
#define MAX_PILOT_SIZE		(2*(TRK_MAX_PILOT_SIZE)+16)
#define MAX_CARR_SIZE		(2*(RB_LEN*MAX_DL_N_RB)+16)

/* Frame Constants */
#define MAX_CP_MODES			2
#define NUM_SUBFRAME_PER_FRAME	10
#define MAX_SLOTS_PER_FRAME		(2*NUM_SUBFRAME_PER_FRAME)
#define N_SYM_CP0				7
#define N_SYM_CP1				6

#define DABS(x)							(((x) >= 0.0)? (x): (-x))
#define ABS(x)							(((x) >= 0)? (x): (-x))
#define WGHT(x,y,w1,w2)					(((w1)*(x) + (w2)*(y))/(w1+w2))
#define CPLX_CONJ_RE(re1,im1,re2,im2)	(((re1)*(re2) + (im1)*(im2))>>15)
#define CPLX_CONJ_IM(re1,im1,re2,im2)	(((im1)*(re2) - (re1)*(im2))>>15)
#define CPLX_RE(re1,im1,re2,im2)		(((re1)*(re2) - (im1)*(im2))>>15)
#define CPLX_IM(re1,im1,re2,im2)		(((im1)*(re2) + (re1)*(im2))>>15)

#define DEMAP_SATMAX	31
#define DEMAP_SATMIN	-31
#define CHAR_SATMAX		127
#define CHAR_SATMIN		-127

//static inline signed char
//SAT_DEMAP(short x)
//{
//	if(x < DEMAP_SATMIN)
//		return DEMAP_SATMIN;
//	else if(x > DEMAP_SATMAX)
//		return DEMAP_SATMAX;
//	else
//		return ((signed char)x);
//}

//static inline signed char
//SAT_CHAR(short x)
//{
//	if(x < CHAR_SATMIN)
//		return CHAR_SATMIN;
//	else if(x > CHAR_SATMAX)
//		return CHAR_SATMAX;
//	else
//		return ((signed char)x);
//}

#ifndef QAM64_FE_BE_RESCALE
#define QAM64_FE_BE_RESCALE			3
#endif

#ifndef QAM16_FE_BE_RESCALE
#define QAM16_FE_BE_RESCALE			3
#endif

#ifndef QPSK_FE_BE_RESCALE
#define QPSK_FE_BE_RESCALE			7
#endif

#ifndef BPSK_FE_BE_RESCALE
#define BPSK_FE_BE_RESCALE			2
#endif

#define SQRT2_SCALE				(12)
#define SQRT2_FIXED				(short)((1.414213)*(1<<SQRT2_SCALE))
#define ONEBYSQRT2_SCALE		(15)
#define ONEBYSQRT2_FIXED		(short)((1<<ONEBYSQRT2_SCALE)/(1.414213))

#define	DEMAP_P1_SCALE		10
#define	DEMAP_P2_SCALE		10
#define	DEMAP_P3_SCALE		10
#define DEMAP_P4_SCALE		10
#define DEMAP_P1			(short)(0.8728*(1<<DEMAP_P1_SCALE))
#define DEMAP_P2			(short)(0.4364*(1<<DEMAP_P2_SCALE))
#define DEMAP_P3			(short)(1.3092*(1<<DEMAP_P3_SCALE))
#define DEMAP_P4			(short)(0.8944*(1<<DEMAP_P4_SCALE))

typedef enum
{
	TRCH_TYPE_BCH,
	TRCH_TYPE_PCH,
	TRCH_TYPE_SCH,
	TRCH_TYPE_RAR
} lte_trch_modes;

typedef enum
{
	TRK_MODE_CONNECTED=1,
	TRK_MODE_BCH=2,
	TRK_MODE_MEASUREMENTS=3
} lte_trk_modes;

typedef enum
{
	DL_TRK_SYSTEM_RESET=-1,
	DL_TRK_END_OF_FILE=-2
} lte_dl_trk_status_en_t;

typedef enum
{
	DL_BCH_CLEAR = 0,
	DL_BCH_SUCCESS,
	DL_BCH_FAIL
} lte_dl_bch_status_en_t;

typedef enum
{
	BPSK=0,
	QPSK,
	QAM16,
	QAM64
} lte_dl_rx_modulation_en_t;

typedef enum
{
	PACKET_PROCESSED=0,
	BCH_PACKET,
	PDSCH_PACKET,
	DL_CRNT_PROC_PACKET
} lte_dl_rx_be_pkt_type_en_t;

/* BE error codes */
typedef enum {
	BE_K_NOT_WITHIN_RANGE = -10,
	BE_NF_NOT_ZERO = -11,
	BE_K_INVALID = -12,
	BE_NC_GREATER_THAN_M = -13,
	BE_N_SYM_LESS_THAN_EQUAL_ZERO = -14,
	BE_INVALID_SBIT = -15,
	BE_INVALID_RV = -16,
	BE_BLOCK_SIZE_GRTR_8Z = -17,
	BE_INVALID_SFNUM = -18,
	BE_INVALID_N_SINGLE_BLOCK = -19,
	BE_INVALID_NCB2 = -20,
	BE_N_OVERFLOWS_CODED_BUFFER = -21,
	BE_N16_OVERFLOWS_SCRAM_BUFFER = -22,
	BE_INVALID_N_MULTI_BLOCK = -23,
	BE_BLOCK_SIZE_GRTR_MAXTBS = -24,
	BE_INVALID_KTYPE = -25,
	BE_INVALID_HPN = -26,
	BE_NCB2_OVERFLOWS_SCRATCHPAD_RM4 = -27,
	BE_NCB2_OVERFLOWS_CR_BUF = -28,
	BE_INVALID_RNTI_TYPE = -29
} lte_be_error_codes;

#define TDD_MAX_NUM_CONFIGS	7

/* TD_LTE */
/* Subframe Assigment: DL-UL configrations */
typedef enum {
        sa0=0, sa1, sa2, sa3, sa4, sa5, sa6
} lte_tdd_ul_dl_config;

/* Special Subframe  Patterns: Special subframe configuration */
typedef enum {
        ssp0=0, ssp1, ssp2, ssp3, ssp4, ssp5, ssp6, ssp7, ssp8
} lte_tdd_special_sf_config;

typedef enum {
	TD_DATASF=0,
	TD_SPCLSF,
	TD_UPLINK,
	FD_DATASF
} lte_subframe_type;

#ifdef ENABLE_MRC
#define MRC(x)	(x)
#else
#define MRC(x)
#endif

/* BCH */
#define SS_SYNC_SCALE		15

// declaration of subroutines used by defines below
int danger_startup_printf( char * format, ... );
int danger_dl_printf( char * format, ... );
int dl_exit_trap( int retval, char * filename, int fileline );
int _my_assert( char * expression, char * callfile, int callline );

#ifdef assert
#  undef assert
#endif

#define assert my_assert

#ifndef my_assert
#    define my_assert( x ) { if (!(x)) { _my_assert(#x,__FILE__,__LINE__); }}
#endif //#ifndef my_assert


//#if(ASSERT_ON==1)
//    #define ASSERT(...) my_assert(__VA_ARGS__);
//#else
//    #define ASSERT(...)
//#endif

#if (PRINTOUT_BE==1)
#  if defined(__SANDBLASTER__) && ALLOW_PUTSTRING
#    define PRINTF_BE(...) __putstring(__VA_ARGS__);
#  else 
#    define PRINTF_BE(...) printf(__VA_ARGS__);
#  endif 
//#else
//#    define PRINTF_BE(...)
//#endif

#if EMBEDDED_LINUX
#  define printf danger_dl_printf
#  define __putstring danger_dl_printf
#elif (defined(ALLOW_PRINTF) && ALLOW_PRINTF==0)
#  ifdef printf
#    undef printf
#  endif
#  define __putstring printf
#elif ALLOW_PUTSTRING==0 || !defined(__SANDBLASTER__)
#  define __putstring printf
#endif

#ifndef USE_SBCC
#define MACH_CYC	0
#endif

#ifndef USE_SBCC
static inline void __sb_barrier()	{}
#endif

#if __SANDBLASTER__
	#define SPIN(_N) {int i; for(i=0; i<_N; i++) __sb_barrier();}
#else
	#define SPIN(_N) sched_yield();
#endif

#define PRINT_BUF(_name, _buf, _n) \
{ \
  int ii; \
  printf("%s\n",_name); \
  for(ii = 0; ii < _n; ii++) \
  { \
    printf("%d: %d\n",ii,(_buf)[ii]); \
  } \
  printf("\n"); \
}

// Does only the icache flush for the overlay (must be done for each thread
// which is using the overlay)
#define LTE_LOAD_OVERLAY_ICACHE_FLUSH(or_)   \
    do { \
      extern void osIcacheFlush(void *start, unsigned size); \
      __SBOVERLAYSYMDECL(or_);               \
      if (__SBOVERLAYCODESIZE(or_) != 0) {        \
        osIcacheFlush(                                \
          __SBOVERLAYVMA(or_),           \
          __SBOVERLAYCODESIZE(or_));     \
        }                                    \
      } while(0)

#define LTE_DL_OVERLAY_LOAD(name_) \
    do { \
      extern void osIcacheFlush(void *start, unsigned size); \
      __SBOVERLAYSYMDECL(name_); \
      memcpy( \
              __SBOVERLAYVMA(name_), \
              __SBOVERLAYLMA(name_), \
              __SBOVERLAYSIZE(name_)); \
      if (__SBOVERLAYCODESIZE(name_) != 0) { \
        osIcacheFlush( \
                       __SBOVERLAYVMA(name_), \
                       __SBOVERLAYCODESIZE(name_)); \
        } \
      } while (0)

#endif /* DL_CONST_H_ */
